import { useState } from 'react';
import * as XLSX from 'xlsx';
import { Progress } from 'antd'; // 引入 Ant Design 的进度条组件
import { Button,Select } from 'antd';
// 定义 Excel 表格常见的最大行数限制（这里以 Excel 2007 及之后版本为例）
const MAX_ROWS_PER_SHEET = 1048576;

// 用于将数据转换为 CSV 格式的字符串，使用 reduce 方法优化了逻辑，使其更加简洁
function arrayToCsv(data) {
    // 使用 reduce 方法迭代数组，acc 为累加器，row 为当前迭代的行。
    return data.reduce((acc, row) => {
        // 将当前行的每个单元格映射到一个新值
        const csvRow = row.map(cell => {
            // 如果单元格是字符串且包含逗号。
            if (typeof cell === 'string' && cell.includes(',')) {
                // 则将逗号替换为两个双引号，并用双引号包裹整个字符串。
                return `"${cell.replace(/"/g, '""')}"`;
            }
            // 否则返回原值
            return cell;
        }).join(',');// 将映射后的单元格数组用逗号连接成一行 CSV。
        return acc + csvRow + '\n';// 将累加器的内容、当前 CSV 行和一个换行符连接，用于累加成最终的 CSV 字符串。
    }, '');// 初始累加器值为空字符串。
}

// 定义名为 ExcelExport 的函数组件，接收一个名为 data 的属性，该组件用于实现将数据导出为不同格式文件的功能
export default function ExcelExport({ data, onProgress }) {
    // format，用于存储用户选择的文件格式，默认为 xlsx。
    const [format, setFormat] = useState('xlsx');
    const [progress, setProgress] = useState(0); // 新增进度状态

    // 定义一个函数，用于创建并下载 Blob 对象。
    const createAndDownloadBlob = (blobData, fileName) => {
        // 创建一个 Blob 对象。
        const blob = new Blob([blobData], { type: blobData.type });
        // 创建一个指向 Blob 对象的 URL
        const url = URL.createObjectURL(blob);
        // 创建一个 a 元素。
        const a = document.createElement('a');
        // 设置 a 元素的 href 属性为 Blob 对象的 URL。
        a.href = url;
        // 设置下载文件的名称。
        a.download = fileName;
        // 模拟点击 a 元素，触发下载操作。
        a.click();
        // 释放之前创建的 URL 对象，避免内存泄漏。
        URL.revokeObjectURL(url);
    };

    // 定义一个名为 exportData 的函数，用于执行具体的导出数据到文件的操作
    const exportData = async () => {
        setProgress(0); // 开始导出时将进度重置为 0
        // 对于 xlsx 和 xls 格式，使用 XLSX 库将数据分块转换为工作簿（因为 Excel 有行限制），然后下载。
        if (format === 'xls' || format === 'xlsx') {
            let workbook = XLSX.utils.book_new();
            let startIndex = 0;
            const totalChunks = Math.ceil(data.length / MAX_ROWS_PER_SHEET);
            for (let i = 0; i < totalChunks; i++) {
                const chunkData = data.slice(startIndex, startIndex + MAX_ROWS_PER_SHEET);
                const worksheet = XLSX.utils.json_to_sheet(chunkData);
                const sheetName = `Sheet${i + 1}`;
                XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
                startIndex += MAX_ROWS_PER_SHEET;
                // 更新进度
                let newProgress = ((i + 1) / totalChunks) * 100;
                setProgress(newProgress); // 更新本地进度状态
                onProgress(newProgress);
                // 每次下载一个块后，设置一个延迟再继续下一个块
                await new Promise((resolve) => setTimeout(resolve, 1000));
            }
            await new Promise((resolve) => {
                XLSX.writeFile(workbook, `data.${format}`);
                resolve();
            });
        } else if (format === 'json') {//对于 json 格式，直接将数据转换为 JSON 字符串并下载。
            const jsonData = JSON.stringify(data);
            createAndDownloadBlob(jsonData, `data.${format}`);
            setProgress(100); // 完成导出，进度设为 100%
            onProgress(100);
        } else if (format === 'csv') {//对于 csv 格式，类似于 xlsx 和 xls 的处理，但使用 arrayToCsv 函数将数据转换为 CSV 字符串，并分块处理（因为 CSV 格式也可能因为内容过长而需要分块处理）。
            let csvContent = '';  // 用于存储当前块的 csv 内容
            let startIndex = 0;
            const totalChunks = Math.ceil(data.length / MAX_ROWS_PER_SHEET);
            for (let i = 0; i < totalChunks; i++) {
                const chunkData = data.slice(startIndex, startIndex + MAX_ROWS_PER_SHEET);
                const csvChunk = arrayToCsv(chunkData);
                startIndex += MAX_ROWS_PER_SHEET;
                // 当达到最大行数限制，即处理下一个块时，将当前块内容添加到总的内容中，并重置当前块内容为空字符串，相当于创建新的内容块
                if (i > 0) {
                    csvContent += '\n';  // 不同内容块之间添加换行，模拟新的表格开始
                }
                csvContent += csvChunk;
                let newProgress = ((i + 1) / totalChunks) * 100;
                setProgress(newProgress); // 更新本地进度状态
                onProgress(newProgress);
                // 用来在分块处理之间添加延迟，以避免阻塞 UI
                await new Promise((resolve) => setTimeout(resolve, 500));
            }
            createAndDownloadBlob(csvContent, `data.${format}`);
        } else {
            console.error('不支持的文件格式');
        }
    }

    return (
        <div style={{ display: 'flex', alignItems: 'center' }}>
            <Button onClick={() => { exportData() }} style={{ marginLeft: '0.5rem', marginBottom:'0.7rem',width: '2.4rem', height: '1rem' }} color="default" variant="outlined">
                        下载
            </Button>
            <Select
      defaultValue="xlsx"
      style={{
        width: 120,
        marginLeft:'0.5rem',
        marginBottom:'0.7rem',
      }}
    //   onChange={handleChange}
    onChange={(e) => {
                setFormat(e.target.value);
            }}
      options={[
        {
          value: 'xlsx',
          label: 'xlsx 格式',
        },
        {
          value: 'xls',
          label: 'xls 格式',
        },
        {
          value: 'json',
          label: 'json 格式',
        },
         {
          value: 'csv',
          label: 'csv 格式',
        },
      ]}
    />


            {/* <select onChange={(e) => {
                setFormat(e.target.value);
            }}>
                <option value="xlsx">xlsx 格式</option>
                <option value="xls">xls 格式</option>
                <option value="json">json 格式</option>
                <option value="csv">csv 格式</option>
            </select> */}
            <Progress
                style={{ marginLeft: 10,marginRight:'0.5rem',marginBottom:'0.7rem', width: 150 }}
                percent={progress}
                status={progress === 100 ? 'success' : 'active'}
            />
        </div>
    )
}